package jers.util;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;

import jers.JERS;

/**
 * Classe utilitaria de recursos de rede.
 * 
 * @author 
 * 		<a href="mailto:felipe.zappala@gmail.com">
 * 			Luis Felipe Zappala
 * 		</a> [ <a href="http://lncc.br/ist">ISTCC-P</a> / 2009 ]
 */
public final class NetworkUtil {
	
	private NetworkUtil() {
		super();
	}
	
	/**
	 * Obtem uma porta livre na maquina.
	 */
	public static int getFreePort() { 
		return getFreePort(0);
	}

	/**
	 * Obtem uma porta livre na maquina indicando uma preferencial por padrao.
	 */
	public static int getFreePort(int defaultPort) {
		int freePort = defaultPort;
		while (true) {
			try {
				if (freePort <= 0) {
					freePort = generatePort();
				}
				ServerSocket ss = new ServerSocket(freePort);
				if (ss.isBound()) {
					ss.close();
					break;
				}
				freePort = generatePort();
			} catch (Exception e) {
				freePort = generatePort();
			}
		}
		return freePort;
	}
	
	/**
	 * Gera um numero de porta aleatorio
	 */
	private static int generatePort() {
		return (int)(1024 + (Math.random() * 65535));
	}
	
	/**
	 * Verifica se a porta passada esta disponivel para uso.
	 */
	public static boolean isFreePort(int port) {
		try {
			if (port <= 0) {
				return false;
			}
			ServerSocket ss = new ServerSocket(port);
			if (ss.isBound()) {
				ss.close();
				return true;
			}
		} catch (Exception e) {
			// Porta ocupada ou sem permissao
		}
		return false;
	}
	
	/**
	 * Obtem o endereco IP principal da maquina.
	 */
	public static String getMainIP() {
		try {
			//FIXME: Resolver problema com mais de um IP na interface de rede
			InetAddress addr = InetAddress.getLocalHost();
			return addr.getHostAddress();
			
		}  catch (Exception e) {
			JERS.log.error(e, "Impossible to define the main IP.");
			return "127.0.0.1";
		}
	}
	
	/**
	 * Obtem uma lista com todos os enderecos IPs resolvidos pela maquina.
	 */
	public static List<String> getIPs() {
		List<String> ips = new LinkedList<String>();
		try {
			Enumeration<NetworkInterface> interfaces 
					= NetworkInterface.getNetworkInterfaces();
			
			while (interfaces.hasMoreElements()) {
				NetworkInterface ni = interfaces.nextElement();
				Enumeration<InetAddress> addrs = ni.getInetAddresses();
				
				while (addrs.hasMoreElements()) {
					InetAddress addr = addrs.nextElement();
					ips.add(addr.getHostAddress());						
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ips;
	}
	
}
